# Copyright (C) 2018-2021 Intel Corporation
# All rights reserved.
#
# 'recipe' for Docker to build an image of centOS 8 based
# environment for building the DAOS project.
#

# Pull base image
ARG BASE_DISTRO=centos:8
FROM $BASE_DISTRO
LABEL maintainer="daos@daos.groups.io"

# Intermittent cache-bust.  Used to reduce load on the actual CACHEBUST later.
ARG CB0

# If a local distro repository is supplied, then we should use it
# and disable using the distro repositories that can be mirrored.
# The Docker image starts out with the DISTRO provided GPG keys
# on the disk, but not installed.  These must be installed before
# adding any repo that needs GPG keys but does not provide meta
# data for installing those keys.  Then the epel-release
# package must be installed and the GPG key it provides must be
# installed.
ARG REPO_URL
ARG REPO_DISTRO
RUN if [ -n "$REPO_DISTRO" ]; then                              \
      rpm --import /etc/pki/rpm-gpg/*;                          \
      MY_REPO="${REPO_URL}${REPO_DISTRO}/";                     \
      MY_NAME="${MY_REPO#*//}";                                 \
      MY_NAME="${MY_NAME//\//_}";                               \
      echo -e "[${MY_NAME}]\n\
name=created from ${MY_REPO}\n\
baseurl=${MY_REPO}\n\
enabled=1\n\
repo_gpgcheck=0\n\
gpgcheck=1\n" >> /etc/yum.repos.d/local-centos-group.repo;      \
      dnf -y install --disablerepo extras --disablerepo baseos  \
          epel-release-8-8.el8 dnf-plugins-core dnf-utils;      \
      rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8;         \
      dnf config-manager --assumeyes --quiet --disable          \
          baseos powertools epel epel-modular extras;           \
      sed "s/^mirrorlist_expire=0*/mirrorlist_expire=99999999/" \
          -i /etc/dnf/dnf.conf;                                 \
      dnf -y upgrade epel-release;                              \
    else                                                        \
      dnf -y install epel-release dnf-plugins-core &&           \
      dnf config-manager --assumeyes --set-enabled powertools;  \
    fi;                                                         \
    dnf clean all

# Currently the appstream REPO can not be part of a repo group
ARG REPO_APSTREAM
RUN if [ -n "$REPO_APPSTREAM" ]; then                           \
      rpm --import /etc/pki/rpm-gpg/*;                          \
      MY_REPO="${REPO_URL}${REPO_APPSTREAM}/";                  \
      MY_NAME="${MY_REPO#*//}";                                 \
      MY_NAME="${MY_NAME//\//_}";                               \
      echo -e "[${MY_NAME}]\n\
name=created from ${MY_REPO}\n\
baseurl=${MY_REPO}\n\
enabled=1\n\
repo_gpgcheck=1\n\
gpgcheck=1\n" >> /etc/yum.repos.d/local-centos-appstream.repo;  \
      dnf config-manager --assumeyes --quiet --disable          \
          appstream;                                            \
    fi

# If a local DAOS repository is supplied, then we should use it
# This is mainly for quickbuilds
ARG REPO_DAOS
RUN if [ -n "$REPO_DAOS" ]; then                                \
      MY_REPO="${REPO_URL}${REPO_DAOS}/";                       \
      MY_NAME="${MY_REPO#*//}";                                 \
      MY_NAME="${MY_NAME//\//_}";                               \
      echo -e "[${MY_NAME}]\n\
name=created from ${MY_REPO}\n\
baseurl=${MY_REPO}\n\
enabled=1\n\
repo_gpgcheck=0\n\
gpgcheck=0\n" >> /etc/yum.repos.d/local-daos-group.repo;        \
    fi

ARG JENKINS_URL
ARG REPOS
RUN for repo in $REPOS; do                                                \
        branch="master";                                                  \
        build_number="lastSuccessfulBuild";                               \
        if [[ $repo = *@* ]]; then                                        \
            branch="${repo#*@}";                                          \
            repo="${repo%@*}";                                            \
            if [[ $branch = *:* ]]; then                                  \
                build_number="${branch#*:}";                              \
                branch="${branch%:*}";                                    \
            fi;                                                           \
        fi;                                                               \
        echo -e "[$repo:$branch:$build_number]\n\
name=$repo:$branch:$build_number\n\
baseurl=${JENKINS_URL}job/daos-stack/job/$repo/job/$branch/$build_number/artifact/artifacts/centos7/\n\
enabled=1\n\
gpgcheck=False\n" >> /etc/yum.repos.d/$repo:$branch:$build_number.repo;   \
        cat /etc/yum.repos.d/$repo:$branch:$build_number.repo; \
        dnf repolist; \
        dnf --disablerepo=\* --enablerepo=$repo:$branch:$build_number makecache; \
    done

# Install OS updates and package.  Include basic tools and daos dependencies
# that come from the core repo.
# Clean up any repos afterwards to save space.
# Switch to dnf as it seems a bit faster.
# libatomic should be in this list, but can not for now due to CI
# post provisioning issue.
# *** Keep these in as much alphbetical order as possible ***
RUN dnf -y upgrade && \
    dnf -y install \
        boost-python3-devel \
        clang-analyzer \
        cmake \
        CUnit-devel \
        e2fsprogs \
        file \
        flex \
        fuse3 \
        fuse3-devel \
        gcc \
        gcc-c++ \
        git \
        glibc-langpack-en \
        golang \
        graphviz \
        hwloc-devel \
        ipmctl \
        java-1.8.0-openjdk \
        json-c-devel \
        libaio-devel \
        libcmocka-devel \
        libevent-devel \
        libipmctl-devel \
        libiscsi-devel \
        libtool \
        libtool-ltdl-devel \
        libunwind-devel \
        libuuid-devel \
        libyaml-devel \
        Lmod \
        lz4-devel \
        make \
        maven \
        meson \
        ndctl \
        ninja-build \
        numactl \
        numactl-devel \
        openmpi-devel \
        openssl-devel \
        patch \
        patchelf \
        pciutils \
        python3-devel \
        python3-distro \
        python3-junit_xml \
        python3-pip \
        python3-pyxattr \
        python3-tabulate \
        python3-scons \
        python3-yaml \
        sg3_utils \
        sudo \
        valgrind-devel \
        yasm && \
    dnf clean all

ARG UID=1000

# Add DAOS users
RUN useradd --uid $UID --user-group --create-home --shell /bin/bash \
            --home /home/daos daos_server
RUN echo "daos_server:daos_server" | chpasswd
RUN useradd --user-group --create-home --shell /bin/bash daos_agent
RUN echo "daos_agent:daos_agent" | chpasswd
RUN echo "daos_server ALL=(root) NOPASSWD: ALL" >> /etc/sudoers.d/daos_sudo_setup

# Create directory for DAOS backend storage
RUN mkdir -p /opt/daos /mnt/daos /var/run/daos_server /var/run/daos_agent &&   \
    chown daos_server.daos_server /opt/daos /mnt/daos /var/run/daos_server &&  \
    chown daos_agent.daos_agent /var/run/daos_agent

# DPDK/SPDK needs pyelftools now
# Longer term, we should upload our RPM build of this to the public packaging
# site and install it by RPM, but for now, we'll just pip install it
USER daos_server:daos_server
RUN python3 -m pip --no-cache-dir --disable-pip-version-check install --user pyelftools
USER root:root

ARG QUICKBUILD=false
ARG QUICKBUILD_DEPS

RUN if $QUICKBUILD; then                                                      \
        echo "Installing: $QUICKBUILD_DEPS";                                  \
        echo "$QUICKBUILD_DEPS" | sed -e '/^$/d' | tr '\n' '\0' |             \
          xargs -0 dnf -y install;                                            \
        dnf clean all;                                                        \
    fi

ARG BULLSEYE
RUN if [ "x$BULLSEYE" != "x" ]; then \
      curl ${JENKINS_URL}job/daos-stack/job/tools/job/master/lastSuccessfulBuild/artifact/bullseyecoverage-linux.tar \
        --retry 10 --retry-max-time 60 --silent --show-error -o bullseye.tar; \
      mkdir -p bullseye; \
      tar -C bullseye --strip-components=1 -xf bullseye.tar; \
      pushd bullseye; \
        ./install --quiet --key "${BULLSEYE}" --prefix /opt/BullseyeCoverage; \
      popd; \
      rm -f bullseye.tar; \
      rm -rf bullseye; \
    fi

# The COPY command has a --chown option but it's not well supported so copy as
# root then run a chown command which is frustrating as the copy can take a few
# seconds.
WORKDIR /home/daos/pre
COPY SConstruct .
COPY site_scons site_scons
COPY utils/build.config utils/
RUN chown -R daos_server.daos_server /home/daos
USER daos_server:daos_server

# Control what to build.  By default Dockerfiles build everything to allow for
# ease-of-use for users, however in CI everything is turned off and then
# selectively enabled.  Turning off any step disables all future steps.
ARG DAOS_DEPS_BUILD=yes
ARG DAOS_KEEP_BUILD=no
ARG DAOS_TARGET_TYPE=release

# Now do an update to ensure software is up to date for the deps build.  If the
# src hasn't changed then this won't do anything, but if it has then we want to
# ensure that latest dependencies are used.
USER root:root
RUN [ "$DAOS_DEPS_BUILD" != "yes" ] || \
    { dnf -y upgrade \
          --exclude=spdk,spdk-devel,dpdk-devel,dpdk,mercury-devel,mercury && \
    dnf clean all; }
USER daos_server:daos_server

ARG DEPS_JOBS=1

RUN [ "$DAOS_DEPS_BUILD" != "yes" ] || \
    { scons-3 --build-deps=yes --jobs $DEPS_JOBS PREFIX=/opt/daos \
      TARGET_TYPE=$DAOS_TARGET_TYPE --deps-only && \
    ([ "$DAOS_KEEP_BUILD" != "no" ] || /bin/rm -rf build *.gz); }

# force an upgrade to get any newly built RPMs
USER root:root
ARG CACHEBUST
RUN dnf -y upgrade \
        --exclude=spdk,spdk-devel,dpdk-devel,dpdk,mercury-devel,mercury && \
    dnf clean all
USER daos_server:daos_server

# Set a label.  This is useful for searching for DAOS images, but is also used
# in github-actions to prune elements of the dockerfile below this point.
LABEL DAOS=stage1

WORKDIR /home/daos/daos/
COPY VERSION LICENSE ftest.sh SConstruct ./
COPY site_scons site_scons
COPY utils utils
COPY src src
USER root:root
RUN chown -R daos_server.daos_server /home/daos/daos/
USER daos_server:daos_server

# select compiler to use
ARG COMPILER=gcc
ARG JOBS=$DEPS_JOBS
ARG DAOS_BUILD_TYPE=$DAOS_TARGET_TYPE
ARG DAOS_BUILD=$DAOS_DEPS_BUILD

# Build DAOS
RUN [ "$DAOS_BUILD" != "yes" ] || \
    { scons-3 --jobs $JOBS install PREFIX=/opt/daos COMPILER=$COMPILER \
      BUILD_TYPE=$DAOS_BUILD_TYPE TARGET_TYPE=$DAOS_TARGET_TYPE && \
    /bin/rm -rf build && go clean -cache && \
    cp -r utils/config/examples /opt/daos; }

# Set environment variables
ENV PATH=/opt/daos/bin:$PATH
ENV FI_SOCKETS_MAX_CONN_RETRY=1

USER root:root
LABEL DAOS=true
USER daos_server:daos_server

# Build java and hadoop bindings
WORKDIR /home/daos/daos/src/client/java
# Set maven repo mirror
RUN mkdir -p /home/daos/.m2
RUN echo -e "<settings>\n\
        <mirrors>\n\
                <mirror>\n\
                        <id>google-maven-central</id>\n\
                        <name>GCS Maven Central mirror</name>\n\
                        <url>https://maven-central.storage-download.googleapis.com/maven2/</url>\n\
                        <mirrorOf>central</mirrorOf>\n\
                </mirror>\n\
        </mirrors>\n\
</settings>" > /home/daos/.m2/settings.xml

ARG DAOS_JAVA_BUILD=$DAOS_BUILD

RUN [ "$DAOS_JAVA_BUILD" != "yes" ] || \
    mvn clean install -T 1C -DskipITs -Dgpg.skip -Ddaos.install.path=/opt/daos
WORKDIR /home/daos

ARG DAOS_KEEP_SRC=no
# Remove local copy
RUN [ $"DAOS_KEEP_SRC" != "no" ] || rm -rf /home/daos/*
